package com.bsoft.ecommerce.config;

import lombok.extern.slf4j.Slf4j;
import org.springframework.cloud.gateway.event.RefreshRoutesEvent;
import org.springframework.cloud.gateway.route.RouteDefinition;
import org.springframework.cloud.gateway.route.RouteDefinitionLocator;
import org.springframework.cloud.gateway.route.RouteDefinitionWriter;
import org.springframework.context.ApplicationEventPublisher;
import org.springframework.context.ApplicationEventPublisherAware;
import org.springframework.stereotype.Service;
import org.springframework.util.CollectionUtils;
import reactor.core.publisher.Mono;
import java.util.List;
/**
 * @program: e-commerce-springclound
 * @description:   事件推送  Aware 动态更新路由网关
 * @author: hdh
 * @create: 2022:06:23 08:49
 */
@Slf4j
@Service
@SuppressWarnings("all")
public class DynamicRouteServiceImpl implements ApplicationEventPublisherAware {
    //写路由 定义
    private final RouteDefinitionWriter routeDefinitionWriter;
    //  获取路由定义
    private final RouteDefinitionLocator routeDefinitionLocator;
    //事件发布
    private ApplicationEventPublisher publisher;
    public DynamicRouteServiceImpl(RouteDefinitionWriter routeDefinitionWriter, RouteDefinitionLocator routeDefinitionLocator) {
        this.routeDefinitionWriter = routeDefinitionWriter;
        this.routeDefinitionLocator = routeDefinitionLocator;
    }
    @Override
    public void setApplicationEventPublisher(ApplicationEventPublisher applicationEventPublisher) {
        // 完成事件推送句柄初始化
        this.publisher = applicationEventPublisher;
    }
    //增加路由定义  刚连接

    public String addRouteDefinition(RouteDefinition definition) {
        log.info("gateway add route [{}]", definition);
        //保存路由发布                                    刷新
        routeDefinitionWriter.save(Mono.just(definition)).subscribe();
        //发布事件通知 给Gateway 同步新增的路由自定义
        this.publisher.publishEvent(new RefreshRoutesEvent(this));
        return "success";
    }
    //路由更新
    //根据路由id 删除路由配置
    private String delectById(String id) {
        try {
            log.info("gateway delete route id [{}]", id);
            this.routeDefinitionWriter.delete(Mono.just(id)).subscribe();
            //发布事件通知给 gateway 更新路由定义
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "delete success";
        } catch (Exception e) {
            log.error("gateway delete route fail", e.getMessage(), e);
            return "delete fail";
        }
    }
    //更新路由    删除
    private String updateByRouteDefinition(RouteDefinition definition) {
        try {
            log.info("gateway update route "+definition);
            // 删除
            this.routeDefinitionWriter.delete(Mono.just(definition.getId()));
        } catch (Exception e) {
            return "update fail ,not find route routeId" + definition.getId();
        }
        try {
            //新增
            this. routeDefinitionWriter.save(Mono.just(definition)).subscribe();
            this.publisher.publishEvent(new RefreshRoutesEvent(this));
            return "scuess";
        }catch (Exception e){
            return "update route fail";
        }
    }
    public  String updateList(List<RouteDefinition> definitionList){
        log.info("gateway update route ",definitionList);
        //当前Gateway 中存储的路由定义
        List<RouteDefinition> routeDefinitionsExist = routeDefinitionLocator.getRouteDefinitions().buffer().blockFirst();
        if(!CollectionUtils.isEmpty(routeDefinitionsExist)){
            //清楚掉之前旧的路由定义
            routeDefinitionsExist.forEach(rd->{
                log.info("delete route definition []",rd);
                delectById(rd.getId());
            });
        }
        //把更新的路由定义到gateway 中
        definitionList.forEach(definition -> updateByRouteDefinition(definition));
        return "sucess";
    }
}
